package com.gitee.srurl.sid.util;

import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

/**
 * sid所需时间戳工具类
 *
 * @author zxw
 * @date 2023/4/25 21:41
 */
@Slf4j
public class SidTimestampHelper {

    /**
     * 当前时间
     */
    private volatile long now;

    /**
     * 当天正常时间做大数值
     * 最大23
     */
    private volatile long theDayOfMaxNormal;

    /**
     * 当天可以获得时间做大数值
     * 最大31
     */
    private volatile long theDayOfMaxBorrow;

    private final long startYear;

    public SidTimestampHelper(long startYear) {
        this.startYear = startYear;
        now = getTimeFromSystem();
        scheduleClockUpdating();
    }

    /**
     * 刷新时间
     */
    private void scheduleClockUpdating() {
        ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor(runnable -> {
            Thread thread = new Thread(runnable, "sid timestamp");
            thread.setDaemon(true);
            return thread;
        });
        scheduler.scheduleAtFixedRate(() -> now = getTimeFromSystem(), 100, 100, TimeUnit.MILLISECONDS);
    }

    /**
     * 从系统中获取时间
     *
     * @return 当前从开始年份到现在以小时为单位的时间
     */
    private long getTimeFromSystem() {

        DateTime current = DateTime.now();
        long year = (long) current.year() - startYear;
        // 只允许127年内
        if (year > 127) {
            log.error("年份信息错误，只允许初始年份后127年的时间，开始年份:{},当前年份:{}", startYear, current.year());
            throw new IllegalArgumentException("年份信息参数错误！");
        }
        int month = current.month() + 1;
        int day = current.dayOfMonth();
        int hour = DateUtil.hour(current, true) - 1;

        this.now = year << 14 | (long) month << 10 | (long) day << 5 | hour;
        this.theDayOfMaxNormal = year << 14 | (long) month << 10 | (long) day << 5 | 23;
        this.theDayOfMaxBorrow = year << 14 | (long) month << 10 | (long) day << 5 | 31;

        return now;
    }

    /**
     * 获取当前时间
     *
     * @return 当前时间
     */
    public long now() {
        return now;
    }

    /**
     * 获取当天正常最大时间
     */
    public long theDayOfMaxNormal() {
        return theDayOfMaxNormal;
    }

    /**
     * 获取一天可以达到的最大时间
     */
    public long theDayOfMaxBorrow() {
        return theDayOfMaxBorrow;
    }
}
